package data;

import graphics.Shape;
import graphics.ShapeFactory;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;
import java.io.PrintWriter;
import java.util.Collections;
import java.util.LinkedList;
import java.util.List;
import java.util.Observable;

import controller.Constants;

/**
 * ShapesData is a singleton class which is used to store shapes for the canvas.
 * 
 * @author Jie Zhao(288654)
 * 
 */
public class ShapesData extends Observable {
	private List<Shape> shapes = null;

	private static ShapesData instance = null;

	private ShapesData() {
		shapes = Collections.synchronizedList(new LinkedList<Shape>());
	}

	/**
	 * Add a shape.
	 * 
	 * @param s
	 */
	public synchronized void addShape(Shape s) {
		if (s != null) {
			shapes.add(s);
			setChanged();
			notifyObservers();
			if(Constants.DEBUG)
			{
				System.out.println("===========Shapes List===========");
				for(Shape j: shapes)
				{
					System.out.println(j);
				}
				System.out.println("===========Shapes List Ends===========");
			}
		}
	}

	/**
	 * remove the given shape
	 * 
	 * @param s
	 */
	public synchronized void removeShape(Shape s) {
		if (s != null) {
			shapes.remove(s);
		}
	}

	/**
	 * Return the data of all shapes.
	 * 
	 * @return
	 */
	public List<Shape> getShapeData() {
		return shapes;
	}

	/**
	 * Return an instance of shapes data.
	 * 
	 * @return
	 */
	public static ShapesData getInstance() {
		if (instance == null) {
			instance = new ShapesData();
		}
		return instance;
	}

	/**
	 * clear all shapes.
	 */
	public synchronized void clear() {
		shapes.clear();
		setChanged();
		notifyObservers();
	}

	/**
	 * Save shapes data to a file
	 * 
	 * @param f
	 * @return true if success;false if any error occurs
	 */
	public synchronized boolean save(File f) {
		// TODO
		try {

			String filename = f.getAbsolutePath();
			if(!filename.endsWith(".dwb"))
			{
				filename += ".dwb";
			}
			File file = new File(filename);
			if (!file.exists()) {
				file.createNewFile();
			}
			PrintWriter pw = new PrintWriter(file);
			for(Shape s:shapes)
			{
				pw.println(s.toString());
			}
			pw.flush();
			pw.close();
			return true;
		} catch (Exception e) {
			e.printStackTrace();
			return false;
		}

	}

	/**
	 * Load the shape data from a file
	 * 
	 * @param f
	 * @return true if success;false if any error occurs
	 */
	public synchronized boolean load(File f) {
		// TODO 
		try {
			if (!f.exists()) {
				return false;
			}
			clear();
			BufferedReader br = new BufferedReader(new FileReader(f));
			String temp = null;
			do
			{
				temp = br.readLine();
				if(temp == null || "".equals(temp))break;
				Shape s = ShapeFactory.createShapeByString(temp);
				s.fromString(temp);
				addShape(s);
			}while(true);
			br.close();
			return true;
		} catch (Exception e) {
			e.printStackTrace();
			return false;
		}
	}
}
